/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.controller;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.SimpleTextRequestMessage;
import cn.easyplatform.messages.vos.EnvVo;
import cn.easyplatform.spi.service.ApplicationService;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.listener.LoginListener;
import cn.easyplatform.web.service.ServiceLocator;
import org.apache.commons.lang3.RandomStringUtils;
import org.zkoss.util.Locales;
import org.zkoss.util.resource.Labels;
import org.zkoss.web.Attributes;
import org.zkoss.web.servlet.http.Encodes;
import org.zkoss.xel.util.SimpleResolver;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.metainfo.ComponentInfo;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zk.ui.util.Composer;
import org.zkoss.zk.ui.util.ComposerExt;
import org.zkoss.zul.*;
import org.zkoss.zul.theme.Themes;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class LoginController implements Composer<Component>,
        ComposerExt<Component> {

    @Override
    public ComponentInfo doBeforeCompose(Page page, Component comp,
                                         ComponentInfo ci) throws Exception {
        EnvVo env = Contexts.getEnv();
        Locale locale = Locales.getCurrent();
        if (locale.toString().equals("zh_HANS_CN"))
            locale = Locale.CHINA;
        if (!env.getLanguages().contains(locale.toString().toLowerCase())) {
            locale = Locales.getLocale(env.getLanguages().get(0));
            Sessions.getCurrent().setAttribute(Attributes.PREFERRED_LOCALE,
                    locale);
            Clients.reloadMessages(locale);
            Locales.setThreadLocal(locale);
        } else
            Sessions.getCurrent().setAttribute(Attributes.PREFERRED_LOCALE,
                    locale);
        Map<String, Object> vars = new HashMap<String, Object>();
        vars.put("$easyplatform", this);
        page.addVariableResolver(new SimpleResolver(vars));
        return ci;
    }

    @Override
    public void doAfterCompose(final Component comp) throws Exception {
        final EnvVo env = Contexts.getEnv();
        comp.getPage().setTitle(env.getTitle());
        Component c = comp.getFellowIfAny("headerTitle");
        if (c != null)
            ((Label) c).setValue(env.getName());
        else {
            Panel panel = (Panel) comp.query("panel");
            if (panel != null)
                panel.setTitle(env.getName());
        }
        String theme = env.getTheme();
        if (!Strings.isBlank(theme))
            Themes.setTheme(Executions.getCurrent(), theme);
        StringBuilder sb = new StringBuilder();
        Component userId = comp.getFellow("userId");
        Component password = comp.getFellow("userPassword");
        Component captcha = comp.getFellowIfAny("captcha");
        Component login = comp.getFellow("login");

        sb.append("if(this.getValue()!=''){var wgt=zk.$('")
                .append(password.getUuid()).append("');wgt.focus();}");
        sb.append("else this.setErrorMessage('")
                .append(Labels.getLabel("user.name.placeholder"))
                .append("')");
        userId.setWidgetListener(Events.ON_OK, sb.toString());

        sb.setLength(0);

        sb.append("if(this.getValue()!=''){var wgt=zk.$('")
                .append(captcha == null ? login.getUuid() : captcha.getUuid()).append("');").append(captcha == null ? "wgt.fire('onClick')}" : "wgt.focus()}");
        sb.append("else this.setErrorMessage('")
                .append(Labels.getLabel("user.password.placeholder"))
                .append("')");
        password.setWidgetListener(Events.ON_OK, sb.toString());

        if (captcha != null) {
            sb.setLength(0);
            sb.append("if(this.getValue()!=''){var wgt=zk.Widget.$('")
                    .append(login.getUuid())
                    .append("');wgt.fire('onClick');}");
            sb.append("else this.setErrorMessage('")
                    .append(Labels
                            .getLabel("user.captcha.placeholder"))
                    .append("')");
            captcha.setWidgetListener(Events.ON_OK, sb.toString());
        }
        sb = null;
        login.addEventListener(Events.ON_CLICK, new LoginListener(env));
        c = comp.getFellowIfAny("languages");
        if (c != null)
            setupLanguage(env, c);

        //设置向导
        final String wizard = Executions.getCurrent().getParameter("wizard");
        if (!Strings.isBlank(wizard)) {
//            IntroJs intro = (IntroJs) comp.query("introJs");
//            if (intro == null)
//                comp.appendChild(intro = new IntroJs());
//            final IntroJs ij = intro;
//            comp.addEventListener("onLater", new EventListener<Event>() {
//                @Override
//                public void onEvent(Event event) throws Exception {
//                    ApplicationService as = ServiceLocator.lookup(ApplicationService.class);
//                    IResponseMessage<?> resp = as.getWizard(new SimpleTextRequestMessage(wizard));
//                    if (resp.isSuccess()) {
//                        List<Step> json = JSON.parseArray((String) resp.getBody(), Step.class);
//                        Options options = new Options();
//                        options.setSteps(json);
//                        ij.addEventListener(IntroJs.ON_NEXT, new WizardEventListener());
//                        ij.setOptionsObj(options);
//                        ij.start();
//                        Sessions.getCurrent().setAttribute("wizard", ij);
//                    } //else
////                        ij.detach();
//                }
//            });
//            Events.echoEvent("onLater", comp, null);
        }
    }

    private void setupLanguage(EnvVo env, Component comp) {
        String locale = Locales.getCurrent().toString().toLowerCase();
        EventListener<Event> el = new SelectLanguageListener();
        if (comp instanceof Combobox) {
            int index = 0;
            for (int i = 0; i < env.getLanguages().size(); i++) {
                String lang = env.getLanguages().get(i);
                Comboitem item = new Comboitem(Labels.getLabel(lang));
                item.setValue(lang);
                comp.appendChild(item);
                if (lang.equals(locale))
                    index = i;
            }
            ((Combobox) comp).setSelectedIndex(index);
            comp.addEventListener(Events.ON_SELECT, el);
        } else if (comp instanceof Menupopup) {
            for (String lang : env.getLanguages()) {
                Menuitem item = new Menuitem(Labels.getLabel(lang));
                item.setValue(lang);
                item.setChecked(locale.equals(lang));
                item.setCheckmark(true);
                item.setAutocheck(true);
                comp.appendChild(item);
                item.addEventListener(Events.ON_CLICK, el);
            }
        }
    }

    private class SelectLanguageListener implements EventListener<Event> {

        @Override
        public void onEvent(Event evt) throws Exception {
            if (evt.getTarget() instanceof Menuitem) {
                for (Component c : evt.getTarget().getParent().getChildren()) {
                    Menuitem item = (Menuitem) c;
                    if (item != evt.getTarget())
                        item.setChecked(false);
                }
                Locale locale = Locales.getLocale(((Menuitem) evt.getTarget())
                        .getValue());
                Sessions.getCurrent().setAttribute(Attributes.PREFERRED_LOCALE,
                        locale);
                Executions.sendRedirect(null);
            } else {
                Combobox cbx = (Combobox) evt.getTarget();
                Locale locale = Locales.getLocale((String) cbx
                        .getSelectedItem().getValue());
                Sessions.getCurrent().setAttribute(Attributes.PREFERRED_LOCALE,
                        locale);
                Executions.sendRedirect(null);
            }
        }

    }

    @Override
    public void doBeforeComposeChildren(Component arg0) throws Exception {

    }

    @Override
    public boolean doCatch(Throwable arg0) throws Exception {
        return false;
    }

    @Override
    public void doFinally() throws Exception {
    }


    public void login(Event event) {
        try {
            new LoginListener(Contexts.getEnv()).onEvent(event);
        } catch (Exception e) {
        }
    }

    /**
     * 第3方登陆
     *
     * @param ref
     * @param type
     */
    public void login(Component ref, String type) {
        ApplicationService as = ServiceLocator.lookup(ApplicationService.class);
        IResponseMessage<?> resp = as.getConfig(new SimpleTextRequestMessage(type));
        if (!resp.isSuccess()) {
            Clients.wrongValue(ref, Labels.getLabel("admin.3rd.not.found"));
        } else {
            Map<String, String> tav = (Map<String, String>) resp.getBody();
            if (type.contains("wx"))
                createWx(tav);
        }
    }

    private void createWx(Map<String, String> tav) {
        StringBuilder sb = new StringBuilder(100);
        try {
            sb.append("https://open.weixin.qq.com/connect/qrconnect?appid=").append(tav.get("appid")).append("&redirect_uri=").append(Encodes.encodeURI(tav.get("redirect"))).append("&response_type=code").append("&scope=snsapi_login&state=").append(RandomStringUtils.random(12, true, true));
            Executions.sendRedirect(sb.toString());
        } catch (Exception e) {
        }
    }

}
